import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.*;
import ca.odell.glazedlists.*;
import ca.odell.glazedlists.swing.*;
import java.text.SimpleDateFormat;
import javax.swing.UIManager;


public class FileBrowserGUI implements ActionListener, ItemListener, MouseListener, WindowListener {


private JFrame frame;
private JTable fileJTable;
private JScrollPane scrollPane;
private JMenuBar menuBar;
private JMenu viewMenu;
private JMenu fileMenu;
private JMenu optionMenu;
private JMenu flavorMenu;
private JMenu configurationMenu;
private JMenuItem setScanInterval;
private JMenuItem addDirectoryItem;
private JMenuItem clearDirectories;
private JMenuItem setScanRoots;
private JMenuItem fileLaunch;
private JMenuItem defaultFileLaunch;
private JMenuItem addViewMenuItem;
private JMenuItem deleteViewMenuItem;
private JMenuItem addFileMenuItem;
private JMenuItem removeFileMenuItem;
private JMenuItem addFilesToViews;
private JMenuItem deleteFilesFromViews;
private JMenuItem addKeyWord;
private JMenuItem deleteKeyWord;
private JMenuItem addExtension;
private JMenuItem deleteExtension;
private JMenuItem maskFile;
private JMenuItem unmaskFile;
private JMenuItem hideMaskFiles;
private JMenuItem seeMaskFiles;
private JLabel search = new JLabel("Search>");
private JButton fileFlavor;
private JButton musicFlavor;
private JButton movieFlavor;
private JButton pictureFlavor;
private UpdateThread update;
private EventList fileEventList;
private EventList viewEventList;
private EventList viewNameList;
private ViewsSelect viewsSelect;
private ConfigurationSingleton config;
private ExtensionKeys extKeys;
public static boolean lockSyncThread = false;
public boolean useHiding = true;
public TableColumnModel colModel;
public static TableColumn nameColumn;
public static TableColumn sizeColumn;
public static TableColumn lastmodColumn;
public static TableColumn extColumn;
public static TableColumn artistColumn;
public static TableColumn genreColumn;
public static TableColumn locationColumn;
public static TableColumn directorColumn;
public static TableColumn previewColumn;
public static TableColumn albumColumn;
public static TableColumn timeColumn;
public static String mode = "music";
public static boolean hideMaskedFiles = false;

  /**
   * Create an FileBrowser GUI
   */
   public FileBrowserGUI() {
   }

   /**
    * Display a frame for browsing issues.
    */
   public void display() {

      //config = ConfigurationSingleton.getConfigurationSingleton();
      loadPersistentObjects();

      // create the view list
      SortedList sortedList = new SortedList(fileEventList, new FileComparator());
      viewsSelect = new ViewsSelect(viewEventList,viewNameList); //change viewselect for no DBReader argument
      FilterList filesForView = new FilterList(sortedList, viewsSelect);
      JTextField filterEdit = new JTextField(10);
      FilterList textFilteredFiles = new FilterList(filesForView,
                                                    new TextComponentMatcherEditor(filterEdit, new FileFilterator()));




      // create the file table
      EventTableModel fileTableModel = new EventTableModel(textFilteredFiles, new FileTableFormat());
      fileJTable = new JTable(fileTableModel);
      TableComparatorChooser tableSorter = new TableComparatorChooser(fileJTable, sortedList, true);
      JScrollPane fileListScrollPane = new JScrollPane(fileJTable);
      fileListScrollPane.setHorizontalScrollBar(new JScrollBar(JScrollBar.HORIZONTAL));
      fileJTable.addMouseListener( this );
      colModel = fileJTable.getColumnModel();

      // customize the table
      fileJTable.setShowVerticalLines(false);
      fileJTable.setGridColor(Color.BLACK);
      fileJTable.setRowHeight(20);
      fileJTable.setFont(new Font("Arial", Font.BOLD, 16));
      fileJTable.setBackground(Color.pink);
      // date in middle
      DateTimeCellRenderer myrenderer = new DateTimeCellRenderer();
      fileJTable.getColumn("Last Modified").setCellRenderer(myrenderer);
      // name on the left
      FileNameRenderer fileNameRenderer = new FileNameRenderer();
      fileJTable.getColumn("Name").setCellRenderer(fileNameRenderer);
      // size on right
      DefaultTableCellRenderer myrenderer2 = new DefaultTableCellRenderer();
      myrenderer2.setHorizontalAlignment(JLabel.RIGHT);
      fileJTable.getColumnModel().getColumn(1).setCellRenderer(myrenderer2);
      // preview for images
      PreviewRenderer previewrenderer = new PreviewRenderer();
      fileJTable.getColumn("Preview").setCellRenderer(previewrenderer);

      // instantiate columns
      nameColumn    = fileJTable.getColumnModel().getColumn(IColumnKeys.s_NAME);
      sizeColumn    = fileJTable.getColumnModel().getColumn(IColumnKeys.s_SIZE);
      lastmodColumn = fileJTable.getColumnModel().getColumn(IColumnKeys.s_LASTMOD);
      extColumn     = fileJTable.getColumnModel().getColumn(IColumnKeys.s_EXTENSION);
      artistColumn  = fileJTable.getColumnModel().getColumn(IColumnKeys.s_ARTIST);
      genreColumn   = fileJTable.getColumnModel().getColumn(IColumnKeys.s_GENRE);
      locationColumn= fileJTable.getColumnModel().getColumn(IColumnKeys.s_DIMENSION);
      directorColumn= fileJTable.getColumnModel().getColumn(IColumnKeys.s_DIRECTOR);
      previewColumn = fileJTable.getColumnModel().getColumn(IColumnKeys.s_PREVIEW);
      albumColumn = fileJTable.getColumnModel().getColumn(IColumnKeys.s_ALBUM);
      timeColumn = fileJTable.getColumnModel().getColumn(IColumnKeys.s_TIME);

      // column width
      nameColumn.setPreferredWidth(225);
      sizeColumn.setPreferredWidth(75);
      sizeColumn.setMaxWidth(100);
      lastmodColumn.setPreferredWidth(175);
      extColumn.setPreferredWidth(75);
      extColumn.setMaxWidth(100);
      previewColumn.setPreferredWidth(60);
      previewColumn.setMaxWidth(60);

      // customize the table column headers
      JTableHeader header = fileJTable.getTableHeader();
      header.setForeground(Color.GRAY);
      header.setBackground(Color.BLACK);
      header.setFont(new Font("Arial Black", Font.ITALIC, 14));
      header.setReorderingAllowed(false);

      // create the view list
      JList viewlist = viewsSelect.getJList();
      viewlist.setFixedCellHeight(20);
      viewlist.setFont(new Font("Arial", Font.BOLD, 16));
      viewlist.setBackground(Color.LIGHT_GRAY);
      JScrollPane viewsListScrollPane = new JScrollPane(viewlist);


      //Create the menu bar.
      menuBar = new JMenuBar();

      //Build Files menu
      fileMenu = new JMenu("Files");
      menuBar.add(fileMenu);

      //Build Views menu.
      viewMenu = new JMenu("Views");
      menuBar.add(viewMenu);

      //Build Flavor menu.
      flavorMenu = new JMenu("Flavors");
      menuBar.add(flavorMenu);

      //Build Option menu.
      optionMenu = new JMenu("Options");
      menuBar.add(optionMenu);

      //Build Configuration menu
      configurationMenu = new JMenu("Configuration");
      menuBar.add(configurationMenu);

      //a group of JMenuItems

      addDirectoryItem = new JMenuItem("Set Scan Directories");
      addDirectoryItem.addActionListener(this);

      setScanInterval = new JMenuItem("Set Scan Interval");
      setScanInterval.addActionListener(this);

      setScanRoots = new JMenuItem("Scan All Roots");
      setScanRoots.addActionListener(this);

      clearDirectories = new JMenuItem("Clear Scan Directories");
      clearDirectories.addActionListener(this);

      addViewMenuItem = new JMenuItem("Add View");
      addViewMenuItem.addActionListener(this);

      deleteViewMenuItem = new JMenuItem("Delete View");
      deleteViewMenuItem.addActionListener(this);

      addFilesToViews = new JMenuItem("Add Files To View");
      addFilesToViews.addActionListener(this);

      deleteFilesFromViews = new JMenuItem("Delete Files From Views");
      deleteFilesFromViews.addActionListener(this);

      addFileMenuItem = new JMenuItem("Add File");
      addFileMenuItem.addActionListener(this);

      removeFileMenuItem = new JMenuItem("Remove File");
      removeFileMenuItem.addActionListener(this);

      fileLaunch = new JMenuItem("Set Launch Application For File");
      fileLaunch.addActionListener(this);

      defaultFileLaunch = new JMenuItem("Set Default Launch Application For File Type");
      defaultFileLaunch.addActionListener(this);

      addKeyWord = new JMenuItem("Add Key Word");
      addKeyWord.addActionListener(this);

      deleteKeyWord = new JMenuItem("Delete Key Word");
      deleteKeyWord.addActionListener(this);

      addExtension = new JMenuItem("Add Extensions");
      addExtension.addActionListener(this);

      deleteExtension = new JMenuItem("Delete Extensions");
      deleteExtension.addActionListener(this);

      maskFile = new JMenuItem("Mask Files");
      maskFile.addActionListener(this);

      unmaskFile = new JMenuItem("Unmask Files");
      unmaskFile.addActionListener(this);

      hideMaskFiles = new JMenuItem("Hide Masked Files");
      hideMaskFiles.addActionListener(this);

      seeMaskFiles = new JMenuItem("See Masked Files");
      seeMaskFiles.addActionListener(this);

      fileMenu.add(addFileMenuItem);
      fileMenu.add(removeFileMenuItem);
      fileMenu.add(addKeyWord);
      fileMenu.add(deleteKeyWord);
      fileMenu.add(fileLaunch);
      fileMenu.add(defaultFileLaunch);
      flavorMenu.add(addExtension);
      flavorMenu.add(deleteExtension);
      optionMenu.add(maskFile);
      optionMenu.add(unmaskFile);
      optionMenu.add(hideMaskFiles);
      optionMenu.add(seeMaskFiles);
      viewMenu.add(addViewMenuItem);
      viewMenu.add(deleteViewMenuItem);
      viewMenu.add(addFilesToViews);
      viewMenu.add(deleteFilesFromViews);
      configurationMenu.add(addDirectoryItem);
      configurationMenu.add(setScanRoots);
      configurationMenu.add(clearDirectories);
      configurationMenu.add(setScanInterval);

      // create the  main panel
      JPanel mainPanel = new JPanel();
      mainPanel.setLayout(new BorderLayout());
      Border title = BorderFactory.createCompoundBorder(
                                  BorderFactory.createEmptyBorder(0,10,10,10),
                                  BorderFactory.createTitledBorder(
                                  BorderFactory.createLineBorder(Color.black,3),
                                  "Files"));
      fileListScrollPane.setBorder(title);
      mainPanel.add(fileListScrollPane, BorderLayout.CENTER);

      //Flavors panle holds flavor button icons
      JPanel flavorsPanel = new JPanel();
      Border title2 = BorderFactory.createCompoundBorder(
                                    BorderFactory.createEmptyBorder(0,10,10,10),
                                    BorderFactory.createTitledBorder(
                                    BorderFactory.createLineBorder(Color.black,3),
                                    "Flavors"));
      flavorsPanel.setBorder(title2);
      String homeDir = config.getHomedir();
      fileFlavor = new JButton("File",new ImageIcon(homeDir+"/lib/Icons/file.gif"));
      fileFlavor.addActionListener( new FlavorButtonPushed() );
      defaultFlavor();
      musicFlavor = new JButton("Music",new ImageIcon(homeDir+"/lib/Icons/music.gif"));
      musicFlavor.addActionListener( new FlavorButtonPushed() );
      movieFlavor = new JButton("Movie",new ImageIcon(homeDir+"/lib/Icons/movie.gif"));
      movieFlavor.addActionListener( new FlavorButtonPushed() );
      pictureFlavor = new JButton("Picture",new ImageIcon(homeDir+"/lib/Icons/picture.gif"));
      pictureFlavor.addActionListener( new FlavorButtonPushed() );
      flavorsPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
      flavorsPanel.add(fileFlavor);
      flavorsPanel.add(musicFlavor);
      flavorsPanel.add(movieFlavor);
      flavorsPanel.add(pictureFlavor);

      //Top menu holds menu bar and button icons
      JPanel topMenu = new JPanel();
      topMenu.setLayout(new BorderLayout());
      topMenu.add(menuBar,BorderLayout.NORTH);
      topMenu.add(flavorsPanel,BorderLayout.SOUTH);
      mainPanel.add(topMenu,BorderLayout.NORTH);

      //west panel holds views
      JPanel westPanel = new JPanel();
      westPanel.setLayout(new BoxLayout(westPanel, BoxLayout.PAGE_AXIS));
      westPanel.setPreferredSize(new Dimension(150, 1000));
      title = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0,10,10,10),
                            BorderFactory.createTitledBorder(
                            BorderFactory.createLineBorder(Color.black,3),
                            "Views"));
      viewsListScrollPane.setBorder(title);
      westPanel.add(viewsListScrollPane);
      mainPanel.add(westPanel, BorderLayout.WEST);

      //filter panel holds filter text field
      JPanel filterPanel = new JPanel();
      filterPanel.add(search);
      filterPanel.add(filterEdit);
      mainPanel.add(filterPanel, BorderLayout.SOUTH);

      // create a frame with main panel
      JFrame frame = new JFrame("File Viewer");
      frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
      frame.addWindowListener(this);

      frame.setSize(1000, 700);
      frame.getContentPane().add(mainPanel);
      frame.setVisible(true);

      (new SyncThread()).start();
      (new UpdateThread()).start();

      //default to either viewing or not viewing masked files
      hideMaskedFiles = config.masked();
      viewsSelect.valueChanged();

   }

   /**
    * save off objects when X'ing out of App
    */
   public void windowClosing(WindowEvent e) {

      persistObject(".fileEventList.dat",fileEventList);
      persistObject(".viewEventList.dat",viewEventList);
      persistObject(".viewNameList.dat",viewNameList);
      persistObject(".config.dat",config);

      // Exit application
      System.exit(0);
   }

   /**
    * make given object persist in given file.
    */
   public void persistObject(String fileName, Object object){
      FileOutputStream fileOut;
      ObjectOutputStream objectOut;

      try {
        fileOut = new FileOutputStream(fileName);
        objectOut = new ObjectOutputStream(fileOut);
        objectOut.writeObject(object);
      } catch (Exception exc){
        System.out.println("Could not write "+ fileName+" object");
        exc.printStackTrace();
      }
   }

   //stubs to support interfaces
   public void windowClosed(WindowEvent e) {}
   public void windowOpened(WindowEvent e) {}
   public void windowIconified(WindowEvent e) {}
   public void windowDeiconified(WindowEvent e) {}
   public void windowActivated(WindowEvent e) {}
   public void windowDeactivated(WindowEvent e) {}
   public void itemStateChanged(ItemEvent e) {}
   public void mousePressed(MouseEvent e){}
   public void mouseReleased(MouseEvent e){}
   public void mouseEntered(MouseEvent e){}
   public void mouseExited(MouseEvent e){}



  /**
   * load persistent objects from disk (if they exist).
   */
   private void loadPersistentObjects(){

      if(!loadPersistentObject(".config.dat")){
         config = new ConfigurationSingleton();
      }
      if(!loadPersistentObject(".fileEventList.dat")){
        fileEventList = new BasicEventList();
      }
      if(!loadPersistentObject(".viewEventList.dat")){
        viewEventList = new BasicEventList();
      }
      if(!loadPersistentObject(".viewNameList.dat")){
        viewNameList = new BasicEventList();
      }
      if(!loadPersistentObject(".extensions.dat")){
        extKeys = new ExtensionKeys();
      }
   }

   public boolean loadPersistentObject(String fileName){
      String persFileName;
      File persFile;
      FileInputStream fileIn;
      ObjectInputStream objectIn;
      boolean ret = false;

      persFileName = fileName;
      persFile = new File(persFileName);
      if (persFile.exists()){
         try {
            fileIn = new FileInputStream(persFileName);
            objectIn = new ObjectInputStream(fileIn);
            if(persFileName.equals(".config.dat")){
               config = (ConfigurationSingleton)objectIn.readObject();
            }
            else if(persFileName.equals(".fileEventList.dat")){
               fileEventList = (BasicEventList)objectIn.readObject();
            }
            else if(persFileName.equals(".viewEventList.dat")){
               viewEventList = (BasicEventList)objectIn.readObject();
            }
            else if(persFileName.equals(".viewNameList.dat")){
               viewNameList = (BasicEventList)objectIn.readObject();
            }
            else if(persFileName.equals(".extensions.dat")){
               extKeys = (ExtensionKeys)objectIn.readObject();
            }
            ret = true;
         } catch (Exception exc) {
            exc.printStackTrace();
            return false;
         }
      }
      else {
         ret = false;
      }
      return ret;
   }

   public static boolean getLockSyncThread(){
      return lockSyncThread;
   }

   public static void setLockSyncThreadFalse(){
      lockSyncThread = false;
   }

   public static void setLockSyncThreadTrue(){
      lockSyncThread = true;
   }


   public void actionPerformed(ActionEvent e){
      JMenuItem source = (JMenuItem)(e.getSource());
      String actionCmd = source.getText();
      if (actionCmd.equals("Set Scan Directories")) {
         AddGUI add = new AddGUI(actionCmd, config);
         add.run();
      }
      else if(actionCmd.equals("Add File")){
         AddGUI add = new AddGUI(actionCmd, fileEventList);
         add.run();
      }
      else if(actionCmd.equals("Scan All Roots")){
         File[] roots = File.listRoots();
           config.addScanDirectories(roots);
      }
      else if(actionCmd.equals("Clear Scan Directories")){
         config.clearScanDirectories();
      }
      else if(actionCmd.equals("Add View")){
         UserInputGUI userInput = new UserInputGUI(actionCmd, viewsSelect);
         userInput.run();
      }
      else if(actionCmd.equals("Delete View")){
         viewsSelect.deleteView();
      }
      else if(actionCmd.equals("Add Files To View")){
         LinkedList files = getSelectedFiles();
         UserInputGUI userInput = new UserInputGUI(actionCmd, viewsSelect, files);
         userInput.run();
      }
      else if(actionCmd.equals("Remove File")){
         LinkedList link = getSelectedFiles();
         ListIterator iterate = link.listIterator(); //files
         while(iterate.hasNext()){
            DBFile tempFile = (DBFile)iterate.next();
            config.addDeletedFile(tempFile);
            fileEventList.getReadWriteLock().writeLock().lock();
            fileEventList.remove(tempFile);
            fileEventList.getReadWriteLock().writeLock().unlock();
         }
      }
      else if(actionCmd.equals("Add Key Word")){
              LinkedList link = getSelectedFiles();
              UserInputGUI userInput = new UserInputGUI(actionCmd, link);
              userInput.run();
      }
      else if(actionCmd.equals("Delete Key Word")){
              LinkedList link = getSelectedFiles();
              UserInputGUI userInput = new UserInputGUI(actionCmd, link);
              userInput.run();
      }
      else if(actionCmd.equals("Set Launch Application For File")){
              LinkedList link = getSelectedFiles();
              AddGUI add = new AddGUI(actionCmd,link);
              add.run();
      }
      else if(actionCmd.equals("Set Default Launch Application For File Type")){
              AddGUI add = new AddGUI(actionCmd,config);
              add.run();
      }
      else if(actionCmd.equals("Delete Files From Views")){
              deleteFilesFromView();
              viewsSelect.valueChanged();
      }
      else if(actionCmd.equals("Set Scan Interval")){
              UserInputGUI userInput = new UserInputGUI(actionCmd, config);
              userInput.run();
      }
      else if(actionCmd.equals("Hide Masked Files")){
              config.hideMaskedFiles();
              //hideMaskedFiles = true;
              viewsSelect.valueChanged();
      }
      else if(actionCmd.equals("See Masked Files")){
              config.seeMaskedFiles();
              //hideMaskedFiles = false;
              viewsSelect.valueChanged();
      }
      else if(actionCmd.equals("Mask Files")){
              LinkedList link = getSelectedFiles();
              Iterator linkIt = link.listIterator();
                 while(linkIt.hasNext()){
                    DBFile temp = (DBFile)linkIt.next();
                    temp.mask();
                 }
              viewsSelect.valueChanged();
      }
      else if(actionCmd.equals("Unmask Files")){
                    LinkedList link = getSelectedFiles();
                    Iterator linkIt = link.listIterator();
                       while(linkIt.hasNext()){
                          DBFile temp = (DBFile)linkIt.next();
                          temp.unMask();
                       }
                    viewsSelect.valueChanged();
      }

  }


   public void deleteFilesFromView(){
         LinkedList files = getSelectedFiles();
         LinkedList views = viewsSelect.getSelectedViews();
         Iterator viewsIt = views.listIterator();
            while(viewsIt.hasNext()){
               Views tempView = (Views)viewsIt.next();
               tempView.deleteFile(files);
               tempView.printFiles();
            }
   }

  /**
   * return List of selected files
   */

   public LinkedList getSelectedFiles(){
      int column = 0;
      if(mode.equals("picture")){
         column = 1;
      }
      LinkedList selectedFiles = new LinkedList();
      int[] rows = fileJTable.getSelectedRows();
      for(int rowNum=0; rowNum<rows.length; rowNum++){
         String unique = (String)fileJTable.getValueAt(rows[rowNum],column);
         ListIterator iter = fileEventList.listIterator(); //files
         while(iter.hasNext()){
            DBFile temp = (DBFile)iter.next();
            if(temp.getPath().equals(unique)){
               selectedFiles.add(temp);
            }
         }
      }
      return selectedFiles;
   }


  /**
   * set default File Flavor View
   */
   public void defaultFlavor(){
     for (int colIndex= colModel.getColumnCount()-1; colIndex>-1; colIndex--) {
        colModel.removeColumn(colModel.getColumn(colIndex));
     }

     mode = "file";
     colModel.addColumn(nameColumn);
     colModel.addColumn(sizeColumn);
     colModel.addColumn(lastmodColumn);
     colModel.addColumn(extColumn);
     }

   public void openFile(String app, String path){
      try{
          String[] cmd = new String[2];
          cmd[0] = app;
          cmd[1] = path;
          Runtime.getRuntime().exec(cmd);
          System.out.println(cmd);
          System.out.println(cmd[0]+" "+cmd[1]);
         }
         catch (IOException ioe){
            ioe.getStackTrace();
         }
   }

   public void mouseClicked(MouseEvent e) {
      String app;
      String path;
      DBFile launchFile = null;
         if( e.getClickCount() == 2 ) {
            LinkedList oneFile = getSelectedFiles();
            Iterator trivialIterator = oneFile.listIterator();
            launchFile = (DBFile)trivialIterator.next();
            path = launchFile.getPath();
            String ext = launchFile.getExt();
               if(launchFile.getLaunchApp() != null){
                  app = launchFile.getLaunchApp();
                  openFile(app,path);
               }
               else if(config.getLaunchApp(ext) != null){
                  app = config.getLaunchApp(ext);
                  openFile(app,path);
               }
               else{
                  JOptionPane.showMessageDialog(new JFrame(),
                  "No Launch Application Has Been Set For This File Or Extension.",
                  "Error",
                  JOptionPane.ERROR_MESSAGE);
               }
           }
       }

   /**
    * Launch the FilesBrowser from the commandline.
    */
   public static void main(String[] args) throws Exception {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      // create the browser
      FileBrowserGUI browser = new FileBrowserGUI();
      browser.display();
   }

  /**
   * scan scanDir for any new files.
   */
   public class UpdateThread extends Thread {
      Date d1 = new Date();
      Date d2 = new Date();
      EventList eventlist;

      public void run() {
         while (true) {
            startWorker();
            try {
               Thread.sleep(config.getUpdateInterval());
               d1 = d2;
               d2 = new Date();
               Long diff = (d2.getTime() - d1.getTime());
               System.out.println("Update: "+diff);
            }
            catch (Exception se) {se.printStackTrace();}
         }
      }

      private void startWorker(){
         int maxLevel = 99;
         Object[] fileObjects = config.getScanDirectories().toArray();
         File[] fi = new File[fileObjects.length];
         for(int fileNum=0;fileNum<fileObjects.length;fileNum++){
            fi[fileNum] = (File)fileObjects[fileNum];
         }
         ThreadWorker worker = new ThreadWorker(fileEventList,fileObjects);
         //this line would call recursive worker
         worker.scanRecursive(fi, 0, maxLevel,config);
         //worker.scanIterative(config);
      }
   }


   public class SyncThread extends Thread {

      public void run() {
         Date d1 = new Date();
         Date d2 = new Date();
         while (true) {
            for (int index=0; index<fileEventList.size(); index++){
               boolean updateNeeded = false;
               //boolean noLongerInScanPath = false;
	         boolean InScanPath = false;


               // The current DBFile in fileEventList
               DBFile dbfileOld = (DBFile)fileEventList.get(index);

               // What would be the new DFFile for that same file
               String absPath = dbfileOld.getPath();
               DBFile dbfileNew = new DBFile(absPath);

               //check to see files are still in scan path
               if(lockSyncThread == false){
                  LinkedList list = config.getScanDirectories();
                  for(int directoryIndex=0;directoryIndex<list.size();directoryIndex++){
                     File fil = (File)list.get(directoryIndex);
                     String st = fil.getPath();
                     if(absPath.startsWith(st) == true){
                        InScanPath = true;
                        break;
                     }
                  }
                  if(InScanPath == false || list.size() == 0){
                     if(!dbfileOld.getMarkProtected()){
                        fileEventList.getReadWriteLock().writeLock().lock();
                        fileEventList.remove(index);
                        fileEventList.getReadWriteLock().writeLock().unlock();
                     }
                  }
               }

               if (!dbfileNew.exists()) {
                  System.out.println("file no longer exists: "+absPath);
                  fileEventList.getReadWriteLock().writeLock().lock();
                  fileEventList.remove(index);
                  fileEventList.getReadWriteLock().writeLock().unlock();

                  continue;
               }
               if (dbfileOld.length() != dbfileNew.length()) {
                  updateNeeded = true;
                  System.out.println(absPath+" size changed");
               }
               if (dbfileOld.lastModified() != dbfileNew.lastModified()) {
                  updateNeeded = true;
                  System.out.println(absPath+" date changed");
               }
               if (dbfileOld.isHidden() != dbfileNew.isHidden()) {
                  updateNeeded = true;
                  System.out.println(absPath+" hidden changed");
               }
               if (dbfileOld.canRead() != dbfileNew.canRead()) {
                  updateNeeded = true;
                  System.out.println(absPath+" can read changed to "+dbfileNew.canRead());
               }
               if (dbfileOld.canWrite() != dbfileNew.canWrite()) {
                  updateNeeded = true;
                  System.out.println(absPath+" can write changed to "+dbfileNew.canWrite());
               }
               if (updateNeeded) {
                  fileEventList.getReadWriteLock().writeLock().lock();
                  fileEventList.set(index, dbfileNew);
                  fileEventList.getReadWriteLock().writeLock().unlock();
               }
            }
            try {
               Thread.sleep(config.getUpdateInterval());
               d1 = d2;
               d2 = new Date();
               Long diff = (d2.getTime() - d1.getTime());
               System.out.println("Sync: "+diff);
            }
            catch (Exception se) {se.printStackTrace();}
         }
      }
   }

   public class FlavorButtonPushed implements ActionListener {

      public void actionPerformed(ActionEvent e){

         for (int colIndex= colModel.getColumnCount()-1; colIndex>-1; colIndex--) {
            colModel.removeColumn(colModel.getColumn(colIndex));
         }

         fileJTable.setRowHeight(20);
         if (e.getSource().equals(musicFlavor)){
            mode = ExtensionKeys.MUSICNAME;;
            colModel.addColumn(nameColumn);
            colModel.addColumn(artistColumn);
            colModel.addColumn(albumColumn);
            colModel.addColumn(genreColumn);
            colModel.addColumn(timeColumn);
         }
         else if (e.getSource().equals(movieFlavor)){
            mode = ExtensionKeys.MOVIENAME;
            colModel.addColumn(nameColumn);
            colModel.addColumn(directorColumn);
            colModel.addColumn(sizeColumn);
         }
         else if (e.getSource().equals(pictureFlavor)){
            mode = ExtensionKeys.PICTURENAME;
            fileJTable.setRowHeight(60);
            colModel.addColumn(previewColumn);
            colModel.addColumn(nameColumn);
            colModel.addColumn(locationColumn);
            colModel.addColumn(sizeColumn);
         }
         else {
            defaultFlavor();
         }
         viewsSelect.valueChanged();
      }
   }
}